import pika, sys, os
from model import create_app, db, User, Userinfo, Unit, Dorm, Room, Information, Order, Orderinfo
from mq import mq_connect
from flask import json
import redis

def main():
    app = create_app()
    app.app_context().push()
    db.create_all()
    channel = mq_connect()
    redis_conn = redis.Redis(host= 'redis', port = 6379, decode_responses=True)

    def callback(ch, method, properties, body):
        # 消息队列中读并且解析数据
        print(" [x] Received %r" % body)
        data = json.loads(body)
        uid = data['uid']
        name = data['name']
        studentid = data['studentID']
        dorm = data['dorm']
        unit = data['unit']
        num = data['num']
        infoname = data['infoname']
        infostudentid = data['infostudentid']

        #存储订单信息到数据库
        #此时不用关联提交订单的人和订单信息，因为订单信息中详细列出了
        userinfo = Userinfo.query.get(uid)
        dorm = Dorm.query.filter_by(dormid = dorm).first()
        filters = {
            Unit.unitid == unit,
            Unit.dorm_id == dorm.id
        }
        unit = Unit.query.filter(*filters).first()
        order = Order(userinfo, unit, userinfo.gender, num, "", 0)
        db.session.add(order)
        orderinfo = Orderinfo(userinfo, order)
        db.session.commit()
        #存储订单信息到redis
        ordername = "order" + str(order.id)
        mapping = {}
        mapping["uid"] = uid
        mapping["name"] = name
        mapping['studentID'] = studentid
        mapping['dorm'] = data['dorm']
        mapping['unit'] = data['unit']
        mapping['num'] = num
        mapping["message"] = order.message
        mapping["status"] = int(order.status)
        mapping["time"] = str(order.time)
        redis_conn.hmset(ordername, mapping)
        

        num = int(num)
        gender = userinfo.gender
        if(num == 1) :
            filters = {
                Userinfo.name == infoname,
                Userinfo.studentid == infostudentid
            } 
            user = Userinfo.query.filter(*filters).first()
            if(user is None):
                order.message = "The user does not exist"
                redis_conn.hset(ordername, "message", order.message)
                return
            #数据库中关联用户订单信息
            orderinfo = Orderinfo(user, order)
            db.session.add(orderinfo)
            db.session.commit()
            # redis中关联用户订单信息
            orders = redis_conn.hget("orderinfo", user.id)
            if(orders):
                orders = orders + " " + ordername
            else:
                orders = ordername
            redis_conn.hset("orderinfo", user.id, orders)
            if(Information.query.filter_by(userinfo_id = user.id).first() is not None):
                order.message = "Repeat application"
                redis_conn.hset(ordername, "message", order.message)
                return
        else:
            for i in range(num):
                name = infoname[i]
                studentid = infostudentid[i]
                filters = {
                    Userinfo.name == name,
                    Userinfo.studentid == studentid
                } 
                user = Userinfo.query.filter(*filters).first()
                if(user is None):
                    order.message = "The user does not exist"                    
                    redis_conn.hset(ordername, "message", order.message)
                    return
                orderinfo = Orderinfo(user, order)
                db.session.add(orderinfo)
                db.session.commit()
                orders = redis_conn.hget("orderinfo", uid)
                if(orders):
                    orders = orders + " " + ordername
                else:
                    orders = ordername
                redis_conn.hset("orderinfo", uid, orders)
                if(user.gender != gender):
                    order.message = "Gender inconsistencies"
                    redis_conn.hset(ordername, "message", order.message)
                    return
                if(Information.query.filter_by(userinfo_id = user.id).first() is not None):
                    order.message = "Repeat application"
                    redis_conn.hset(ordername, "message", order.message)
                    return                
            
        rooms = Room.query.filter_by(unit_id = unit.id).all()
        for room in rooms:
            if(room.rest >= num):
                order.status = 1
                redis_conn.hset(ordername, "status", order.status)
                room.rest -= num
                rest = redis_conn.hget("dormlist", "dorm" + str(dorm.id) + "unit" + str(unit.id))
                if(rest):
                    redis_conn.hset("dormlist", "dorm" + str(dorm.id) + "unit" + str(unit.id), int(rest) - num)
                if num == 1:
                    filters = {
                        Userinfo.name == infoname,
                        Userinfo.studentid == infostudentid
                    } 
                    user = Userinfo.query.filter(*filters).first()
                    info = Information(user, room)
                    db.session.add(info)
                    db.session.commit()
                    redis_conn.hset(ordername, "room", room.roomid)
                else:
                    for i in range(num):
                        name = infoname[i]
                        studentid = infostudentid[i]
                        filters = {
                            Userinfo.name == name,
                            Userinfo.studentid == studentid
                        } 
                        user = Userinfo.query.filter(*filters).first()
                        info = Information(user, room)
                        db.session.add(info)
                        db.session.commit()
                        redis_conn.hset(ordername, "room", room.roomid)
                    
                order.message = "successful"
                redis_conn.hset(ordername, "message", order.message)
                return
                    
        order.message = "too many people"
        redis_conn.hmset(ordername, "message", order.message)
        return
    channel.basic_consume(queue='hello', on_message_callback=callback, auto_ack=True)

    print(' [*] Waiting for messages. To exit press CTRL+C')
    channel.start_consuming()

if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        print('Interrupted')
        try:
            sys.exit(0)
        except SystemExit:
            os._exit(0)